<template>
    <div class="scatter-diagram" ref="parent">
        <svg class="scatter"></svg>
    </div>
</template>

<script>
///<reference path="../../typings/index.d.ts"/>
//d.ts提供智能提示
//假如删除上面的reference,下面的代码里就无法识别出d3.select等api
import d3 from "d3";
import host from "../xhr";
import scatterFoobarData from "../foobar-data/scatter-points";
import Color from "color";
// debugger

export default {
  name: "Scatter-Diagram",
  data() {
    return {
      points: []
    };
  },
  mounted: function() {
    const ParentSelection = d3.select(this.$refs["parent"]);
    const Svg = ParentSelection.select("svg.scatter");
    const svg = Svg;
    const outer_width = 400,
      outer_height = 400;
    const padding = {
      left: 30,
      right: 30,
      top: 30,
      bottom: 30
    };
    const width = outer_width - padding.left - padding.right;
    const height = outer_height - padding.top - padding.bottom;
    Svg.attr("width", outer_width).attr("height", outer_height);
    const xScale = d3.scale
      .linear()
      .range([padding.left, padding.left + width]);
    const yScale = d3.scale.linear().range([padding.top, padding.top + height]);
    const colorScale = d3.scale.category10().domain([-Infinity, 10]);
    const xAxis = d3.svg.axis().orient("bottom");
    const yAxis = d3.svg.axis().orient("left");
    const g_for_xAxis = svg
      .append("g")
      .classed("axis", true)
      .attr("transform", `translate(0,${padding.top + height})`);
    const g_for_yAxis = svg
      .append("g")
      .classed("axis", true)
      .attr("transform", `translate(${padding.left},0)`);
    let circles_for_points = svg.selectAll("circle.scatter"); //这里要等待XHR的结果才能调用data()
    const that = this;
    const x_scale_domains = [];
    const y_scale_domains = [];
    const draw_points = function drawPoints() {
      // debugger;
      circles_for_points
        .transition()
        .duration(500)
        .attr("cx", d => {
          // debugger
          return xScale(d.x);
        })
        .attr("cy", d => {
          return yScale(d.y);
        })
        .attr("r", 5)
        .attr("comment", d => JSON.stringify(d))
        .attr("fill", d => colorScale(d.label));
    };
    const draw_axises = function drawAxises() {
      xAxis.scale(xScale);
      yAxis.scale(yScale);
      g_for_xAxis
        .transition()
        .duration(500)
        .call(xAxis);
      g_for_yAxis
        .transition()
        .duration(500)
        .call(yAxis);
    };
    +(function init() {
      d3.json(host("scatter-points")).get((err, data) => {
        if (err) {
          console.warn("request failed");
          that.$notify.error("[scatter]mysql connect failed;try use test data");
          that.points = scatterFoobarData["points"];
        } else {
          that.points = data["points"];
        }
        circles_for_points = circles_for_points
          .data(that.points)
          .enter()
          .append("circle")
          .classed("scatter", true);
        xScale.domain([
          d3.min(that.points, d => d.x),
          d3.max(that.points, d => d.x)
        ]);
        yScale.domain([
          d3.max(that.points, d => d.y),
          d3.min(that.points, d => d.y)
        ]);
        x_scale_domains.push(xScale.domain());
        y_scale_domains.push(yScale.domain());
        draw_points();
        draw_axises();
        //add brush
        const brush = d3.svg
          .brush()
          .x(xScale)
          .y(yScale);
        const g_for_brush = svg.append("g").call(brush);
        g_for_brush.selectAll("rect").style("fill-opacity", 0.3);
        brush.on("brushend", function() {
          let extent = brush.extent();
          if (extent[0][0] != extent[1][0]) {
            xScale.domain([
              d3.min(extent, d => d[0]),
              d3.max(extent, d => d[0])
            ]);
            yScale.domain([
              d3.max(extent, d => d[1]),
              d3.min(extent, d => d[1])
            ]);
            x_scale_domains.push(xScale.domain());
            y_scale_domains.push(yScale.domain());
            draw_points();
            draw_axises();
            g_for_brush.call(brush.clear()); //删除矩形选择框
          }
        });
        svg.on("wheel", () => {
          let wheel_event = d3.event;
          wheel_event.preventDefault();//需要组织页面的向下滚动
          let deltaY = wheel_event.deltaY;
          if (deltaY > 0) {
            let length = x_scale_domains.length;
            if (length > 1) {
              xScale.domain(x_scale_domains[length - 2]);
              x_scale_domains.pop();
              yScale.domain(y_scale_domains[length - 2]);
              y_scale_domains.pop();
              draw_axises();
              draw_points();
            }
          }
        });
      });
    })();
  },
  methods: {},
  watch: {}
};
</script>
<style lang="scss">
.scatter-diagram {
  svg.scatter {
    g.axis {
      path,
      line {
        fill: none;
        stroke: hsla(330, 113%, 26%, 1);
        shape-rendering: crispEdges;
      }
      text {
        fill: #ff0080;
        font-size: 11px;
        font-family: sans-serif;
      }
    }
    circle.scatter {
      fill-opacity: 0.3;
    }
  }
}
</style>

